package yxy.game.pm2.bean;

import org.joda.time.DateTime;
import org.redisson.api.RBucket;
import yxy.apple.util.RandomStringUtility;
import yxy.apple.util.redisson.RedisConnection;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.game.base.bean.GatewayBean;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.bean.db.dao.MySQLCacheDAO;
import yxy.game.pm2.bean.module.BaseGameRedisBean;
import yxy.game.pm2.bean.pubsub.PlayerBeanPublisher;

import java.util.ArrayList;
import java.util.Collection;

public class PlayerBean extends BaseGameRedisBean {

    // bean===========================================================================

    private int uid;// 用户id

    private int serverId;
    private String code;
    private String name;
    private int avatar; // 形象
    private int head; // 头像
    private int headframe; // 头像框
    private int title; // 称号
    private String union; // 联盟code
    private String grading; // 段位
    private int level;
    private int viplevel;
    private long power;// 普通阵型的战力
    private DateTime updateTime;// 更新时间
    private String guide;// 新手引导信息
    private int town;// 地区id
    private int city;// 城市id

    // XXX 临时用 之后要换到统计服查询
    private DateTime createTime;// 角色创建时间
    private DateTime upgradeTime;// 角色升级时间

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public int getServerId() {
        return serverId;
    }

    public void setServerId(int serverId) {
        this.serverId = serverId;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAvatar() {
        return avatar;
    }

    public void setAvatar(int avatar) {
        this.avatar = avatar;
    }

    public int getHead() {
        return head;
    }

    public void setHead(int head) {
        this.head = head;
    }

    public int getHeadframe() {
        return headframe;
    }

    public void setHeadframe(int headframe) {
        this.headframe = headframe;
    }

    public int getTitle() {
        return title;
    }

    public void setTitle(int title) {
        this.title = title;
    }

    public String getUnion() {
        return union;
    }

    public void setUnion(String union) {
        this.union = union;
    }

    public String getGrading() {
        return grading;
    }

    public void setGrading(String grading) {
        this.grading = grading;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getViplevel() {
        return viplevel;
    }

    public void setViplevel(int viplevel) {
        this.viplevel = viplevel;
    }

    public long getPower() {
        return power;
    }

    public void setPower(long power) {
        this.power = power;
    }

    public DateTime getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(DateTime updateTime) {
        this.updateTime = updateTime;
    }

    public String getGuide() {
        return guide;
    }

    public void setGuide(String guide) {
        this.guide = guide;
    }

    public int getTown() {
        return town;
    }

    public void setTown(int town) {
        this.town = town;
    }

    public int getCity() {
        return city;
    }

    public void setCity(int city) {
        this.city = city;
    }

    public DateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(DateTime createTime) {
        this.createTime = createTime;
    }

    public DateTime getUpgradeTime() {
        return upgradeTime;
    }

    public void setUpgradeTime(DateTime upgradeTime) {
        this.upgradeTime = upgradeTime;
    }

    // func==========================================================================

    /**
     * 判断角色是否在线
     */
    public boolean online() {
        try {
            RedisConnection redis = RedisManager.getInstance().getConnection(RedisType.REDIS_USER);
            GatewayBean gatewayBean = GatewayBean.find(redis, getUid());
            if (gatewayBean == null) {
                return false;
            }
            return gatewayBean.getPcode().equals(getCode());
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return false;
    }

    // redis==========================================================================

    static public String key(String playerCode) {
        return String.format("PLAYER:%s:INFO", playerCode);
    }

    public void set() {
        try {
            setv(key(getCode()), this);
            PlayerBeanPublisher.getInstance().publish(this);
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    public static void saveToDB(String playerCode) {
        try {
            String key = key(playerCode);
            if (touchBucket(key).isExists()) {
                PlayerBean playerBean = PlayerBean.get(playerCode);
                MySQLCacheDAO.setV(key, playerBean);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void removeAllFromRedis(String playerCode) {
        try {
            touchBucket(key(playerCode)).delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static public PlayerBean get(String playerCode) {
        try {
            String key = key(playerCode);

            PlayerBean playerBean = getv(key);
            if (playerBean == null) {
                playerBean = MySQLCacheDAO.getV(key, PlayerBean.class);
                if (playerBean != null) playerBean.set();
            }

//			PlayerBean playerBean = getv(key(playerCode));
            return playerBean;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成一个新角色
     */
    static public PlayerBean create(int uid, int serverId) throws RedisException {
        String code = RandomStringUtility.randomLowerNumeric(6);
        RBucket<PlayerBean> bucket = touchBucket(key(code));
        while (bucket.isExists()) {
            code = RandomStringUtility.randomLowerNumeric(6);
//			bucket = touchBucket(key(code));
        }

        PlayerBean player = new PlayerBean();
        player.setServerId(serverId);
        player.setCode(code);
        player.setUid(uid);
        player.setLevel(0);
        player.setViplevel(0);
        player.setName(code);

        DateTime now = DateTime.now();
        player.setCreateTime(now);
        player.setUpgradeTime(now);

        player.set();
//		bucket.set(player);
        return player;
    }

    public static PlayerBean create(int uid, int serverId, String code) throws RedisException {
//		RBucket<PlayerBean> bucket = touchBucket(key(code));

        PlayerBean player = new PlayerBean();
        player.setServerId(serverId);
        player.setCode(code);
        player.setUid(uid);
        player.setLevel(0);
        player.setViplevel(0);
        player.setName(code);

        DateTime now = DateTime.now();
        player.setCreateTime(now);
        player.setUpgradeTime(now);

        player.set();
//		bucket.set(player);
        return player;
    }

    /**
     * 正常情况下不要使用这个方法
     */
    static public Collection<PlayerBean> all() {
        ArrayList<PlayerBean> list = new ArrayList<>();
        try {
            Iterable<String> iterable = redis().client().getKeys().getKeysByPattern(key("*"));
            for (String code : iterable) {
                PlayerBean bean = getv(code);
                if (bean != null) {
                    list.add(bean);
                }
            }
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return list;
    }

    // lock==========================================================================

    @Override
    public String lockKey() {
        return String.format("lock:%s", key(getCode()));
    }

}
